AOP是在處理Cross-cutting concerns,將某段代碼(日誌)動態切入(不把日誌程式hardcode到業務邏輯方法中)到指定方法(加減乘除)的指定位置進行運行。
昨天我們學到了AOP中Around Advice的執行順序與透過空方法可以將pointcut expression抽出來重用
今日我們將探討AOP在多個Aspect的Advice的運行順序
Log切面
@Aspect
@Component
@Order(1)
public class LogUtils {
@Pointcut(value = "execution(public int com.swj.MyCalculator.*(..))")
public void pointCutExpressionShare(){}
@Around("pointCutExpressionShare()")
public Object aroundAdvice(ProceedingJoinPoint pjp){
Object[] params = pjp.getArgs();
String methodName = pjp.getSignature().getName();
Object proceed =null;
try {
//Before
System.out.println("[LogUtils-Around Before]"+"["+methodName+"]");
//目標方法invoke
proceed = pjp.proceed(params);
//AfterReturning
System.out.println("[LogUtils-Around AfterReturning]"+"["+methodName+"]");
}catch (Throwable e){
//AfterThrowing
System.out.println("[LogUtils-Around AfterThrowing]"+"["+methodName+"]");
// throw new RuntimeException(e);
}finally {
//After
System.out.println("[LogUtils-Around After]"+"["+methodName+"]");
}
return proceed;
}
@Before("pointCutExpressionShare()")
public static void logStart(JoinPoint jointPoint){
System.out.println("[LogUtils-Before]"+"["+jointPoint.getSignature().getName()+"] method start,parameter:"+Arrays.asList(jointPoint.getArgs()));
}
@AfterReturning(value = "pointCutExpressionShare()",returning = "result")
public static void logReturn(JoinPoint joinPoint, Object result){
System.out.println("[LogUtils-AfterReturning]"+"["+joinPoint.getSignature().getName()+"] method completed,result is "+result);
}
@After("pointCutExpressionShare()")
public static void logEnd(JoinPoint joinPoint){
System.out.println("[LogUtils-After]"+"["+joinPoint.getSignature().getName()+"] method end");
}
@AfterThrowing(value = "pointCutExpressionShare()",throwing = "exception")
public static void logException(JoinPoint joinPoint,Exception exception){
System.out.println("[LogUtils-AfterThrowing]"+"["+joinPoint.getSignature().getName()+"] method throws exception:"+exception);
}
}
Audit切面
@Aspect
@Component
@Order(2)
public class AuditUtils {
// @Around("com.swj.LogUtils.pointCutExpressionShare()")
public Object aroundAdvice(ProceedingJoinPoint pjp){
Object[] params = pjp.getArgs();
String methodName = pjp.getSignature().getName();
Object proceed =null;
try {
//Before
System.out.println("[AuditUtils-Around Before]"+"["+methodName+"]");
//目標方法invoke
proceed = pjp.proceed(params);
//AfterReturning
System.out.println("[AuditUtils-Around AfterReturning]"+"["+methodName+"]");
}catch (Throwable e){
//AfterThrowing
System.out.println("[AuditUtils-Around AfterThrowing]"+"["+methodName+"]");
}finally {
//After
System.out.println("[AuditUtils-Around After]"+"["+methodName+"]");
}
return proceed;
}
@Before("com.swj.LogUtils.pointCutExpressionShare()")
public static void logStart(JoinPoint jointPoint){
//取得方法名稱,與parameter
System.out.println("[AuditUtils-Before]"+"["+jointPoint.getSignature().getName()+"] method start,parameter:"+Arrays.asList(jointPoint.getArgs()));
}
@AfterReturning(value = "com.swj.LogUtils.pointCutExpressionShare()",returning = "result")
public static void logReturn(JoinPoint joinPoint, Object result){
System.out.println("[AuditUtils-AfterReturning]"+"["+joinPoint.getSignature().getName()+"] method completed,result is "+result);
}
@After("com.swj.LogUtils.pointCutExpressionShare()")
public static void logEnd(JoinPoint joinPoint){
System.out.println("[AuditUtils-After]"+"["+joinPoint.getSignature().getName()+"] method end");
}
@AfterThrowing(value = "com.swj.LogUtils.pointCutExpressionShare()",throwing = "exception")
public static void logException(JoinPoint joinPoint,Exception exception){
System.out.println("[AuditUtils-AfterThrowing]"+"["+joinPoint.getSignature().getName()+"] method throws exception:"+exception);
}
}
Result
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- <context:component-scan base-package="com.swj"></context:component-scan>-->
<!-- <!– 啟動AOP –>-->
<!-- <aop:aspectj-autoproxy></aop:aspectj-autoproxy>-->
<bean id="myCalculator" class="com.swj.MyCalculator"></bean>
<bean id="logUtils" class="com.swj.LogUtils"></bean>
<bean id="auditUtils" class="com.swj.AuditUtils"></bean>
<aop:config>
<!-- 將pointcut expression抽出來 -->
<aop:pointcut id="myPointcut" expression="execution(public int com.swj.MyCalculator.*(..))"/>
<aop:aspect ref="logUtils">
<aop:before method="logStart" pointcut-ref="myPointcut"></aop:before>
<aop:after-returning method="logReturn" pointcut-ref="myPointcut" returning="result"></aop:after-returning>
<aop:after-throwing method="logException" pointcut-ref="myPointcut" throwing="exception"></aop:after-throwing>
<aop:after method="logEnd" pointcut-ref="myPointcut"></aop:after>
<aop:around method="aroundAdvice" pointcut-ref="myPointcut"></aop:around>
</aop:aspect>
<aop:aspect ref="auditUtils">
<aop:before method="logStart" pointcut-ref="myPointcut"></aop:before>
<aop:after-returning method="logReturn" pointcut-ref="myPointcut" returning="result"></aop:after-returning>
<aop:after-throwing method="logException" pointcut-ref="myPointcut" throwing="exception"></aop:after-throwing>
<aop:after method="logEnd" pointcut-ref="myPointcut"></aop:after>
<aop:around method="aroundAdvice" pointcut-ref="myPointcut"></aop:around>
</aop:aspect>
</aop:config>
</beans>
@Test
public void testDay22(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("bean22.xml");
System.out.println("容器啟動完成....");
MyCalculator calculator = ioc.getBean(MyCalculator.class);
calculator.add(1,1);
System.out.println("=================");
calculator.div(1,0);
}
Result